﻿using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Metadata;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System;
using System.Collections.Generic;
using System.Data.Services.Common;
using System.Runtime.Serialization;

namespace Sustainalytics.DynamicsCRMGateway.Entities
{
    [DataContractAttribute(IsReference = true)]
    [EntityLogicalNameAttribute("account")]
    [DataServiceKeyAttribute("Id")]
    [EntityAttribute("AccountSet")]
    public class Account : CrmEntity, INameable
    {
        public Account() :
            base(EntityLogicalName)
        {
        }

        public const string EntityLogicalName = "account";

        [AttributeLogicalNameAttribute("accountid")]
        public Nullable<Guid> AccountId
        {
            get { return this.GetAttributeValue<Nullable<Guid>>("accountid"); }
            set { this.SetPrimaryIdAttributeValue<Nullable<Guid>>("AccountId", "accountid", value); }
        }

        [AttributeLogicalNameAttribute("accountid")]
        public override Guid Id
        {
            get { return base.Id; }
            set { this.AccountId = value; }
        }

        [AttributeLogicalNameAttribute("name")]
        public string Name
        {
            get { return this.GetAttributeValue<string>("name"); }
            set { this.SetAttributeValue<string>("Name", "name", value); }
        }

        [AttributeLogicalNameAttribute("customertypecode")]
        public Nullable<int> RelationshipType
        {
            get { return this.GetAttributeValue<Nullable<int>>("customertypecode"); }
            set { this.SetAttributeValue<OptionSetValue>("CustomerTypeCode", "customertypecode", value); }
        }
        [AttributeLogicalNameAttribute("statecode")]
        public int Status
        {
            get { return this.GetAttributeValue<int>("statecode"); }
            set { this.SetAttributeValue<int>("StateCode", "statecode", value); }
        }

        [RelationshipSchemaNameAttribute("new_account_new_accountfeature_Account")]
        public IEnumerable<AccountFeature> AccountFeatures
        {
            get { return this.GetRelatedEntities<AccountFeature>("new_account_new_accountfeature_Account", null); }
            set { this.SetRelatedEntities<AccountFeature>("new_account_new_accountfeature_Account", "new_account_new_accountfeature_Account", null, value); }
        }

        [RelationshipSchemaNameAttribute("new_account_new_accountuniverse_Account")]
        public IEnumerable<AccountUniverse> AccountUniverses
        {
            get { return this.GetRelatedEntities<AccountUniverse>("new_account_new_accountuniverse_Account", null); }
            set { this.SetRelatedEntities<AccountUniverse>("new_account_new_accountuniverse_Account", "new_account_new_accountuniverse_Account", null, value); }
        }

        [RelationshipSchemaNameAttribute("new_account_new_companiesgroup")]
        public IEnumerable<CompaniesGroup> CompaniesGroups
        {
            get { return this.GetRelatedEntities<CompaniesGroup>("new_account_new_companiesgroup", null); }
            set { this.SetRelatedEntities<CompaniesGroup>("new_account_new_companiesgroup", "new_account_new_companiesgroup", null, value); }
        }

        /// <summary>
        /// Constructor for populating via LINQ queries given a LINQ anonymous type
        /// <param name="anonymousType">LINQ anonymous type.</param>
        /// </summary>
        public Account(object anonymousType) :
            this()
        {
            foreach (var p in anonymousType.GetType().GetProperties())
            {
                var value = p.GetValue(anonymousType, null);
                if (p.PropertyType == typeof(Guid))
                {
                    // Type is Guid, must be Id
                    base.Id = (Guid)value;
                    Attributes["accountid"] = base.Id;
                }
                else if (p.Name == "FormattedValues")
                {
                    // Add Support for FormattedValues
                    FormattedValues.AddRange((FormattedValueCollection)value);
                }
                else
                {
                    Attributes[p.Name.ToLowerInvariant()] = value;
                }
            }
        }
    }
}
